//
// Copyright (c) ZeroC, Inc. All rights reserved.
//

#pragma once

[[cpp:include(deque)]]
[[cpp:include(list)]]
[[cpp:include(MyByteSeq.h)]]
[[cpp:include(CustomMap.h)]]
[[cpp:include(CustomBuffer.h)]]
[[cpp:include(StringView.h)]]

module Test
{

sequence<bool> BoolSeq;
[cpp:type(std::list<bool>)] sequence<bool> BoolList;

[cpp:type(std::list< ::Test::BoolList>)] sequence<BoolList> BoolListList;
sequence<BoolList> BoolListSeq;
[cpp:type(std::list< ::Test::BoolSeq>)] sequence<BoolSeq> BoolSeqList;

sequence<byte> ByteSeq;
[cpp:type(std::list< ::Ice::Byte>)] sequence<byte> ByteList;

[cpp:type(std::list< ::Test::ByteList>)] sequence<ByteList> ByteListList;
sequence<ByteList> ByteListSeq;
[cpp:type(std::list< ::Test::ByteSeq>)] sequence<ByteSeq> ByteSeqList;

sequence<string> StringSeq;
[cpp:type(std::list<std::string>)] sequence<string> StringList;

[cpp:type(std::list< ::Test::StringList>)] sequence<StringList> StringListList;
sequence<StringList> StringListSeq;
[cpp:type(std::list< ::Test::StringSeq>)] sequence<StringSeq> StringSeqList;

struct Fixed
{
    short s;
}

sequence<Fixed> FixedSeq;
[cpp:type(std::list< ::Test::Fixed>)] sequence<Fixed> FixedList;

[cpp:type(std::list< ::Test::FixedList>)] sequence<FixedList> FixedListList;
sequence<FixedList> FixedListSeq;
[cpp:type(std::list< ::Test::FixedSeq>)] sequence<FixedSeq> FixedSeqList;

struct Variable
{
    string s;
    BoolList bl;
    [cpp:type(std::list<std::string>)] StringSeq ss;
}

sequence<Variable> VariableSeq;
[cpp:type(std::list< ::Test::Variable>)] sequence<Variable> VariableList;

[cpp:type(std::list< ::Test::VariableList>)] sequence<VariableList> VariableListList;
sequence<VariableList> VariableListSeq;
[cpp:type(std::list< ::Test::VariableSeq>)] sequence<VariableSeq> VariableSeqList;

dictionary<string, string> StringStringDict;
sequence<StringStringDict> StringStringDictSeq;
[cpp:type(std::list< ::Test::StringStringDict>)] sequence<StringStringDict> StringStringDictList;

[cpp:type(std::list< ::Test::StringStringDictList>)] sequence<StringStringDictList> StringStringDictListList;
sequence<StringStringDictList> StringStringDictListSeq;
[cpp:type(std::list< ::Test::StringStringDictSeq>)] sequence<StringStringDictSeq> StringStringDictSeqList;

enum E { E1, E2, E3 }
sequence<E> ESeq;
[cpp:type(std::list< ::Test::E>)] sequence<E> EList;

[cpp:type(std::list< ::Test::EList>)] sequence<EList> EListList;
sequence<EList> EListSeq;
[cpp:type(std::list< ::Test::ESeq>)] sequence<ESeq> ESeqList;

class C {}
sequence<C> CSeq;
[cpp:type(std::list<std::shared_ptr<::Test::C>>)] sequence<C> CList;

[cpp:type(std::list< ::Test::CList>)] sequence<CList> CListList;
sequence<CList> CListSeq;
[cpp:type(std::list< ::Test::CSeq>)] sequence<CSeq> CSeqList;

interface D{}
sequence<D*> DPrxSeq;
[cpp:type(std::list<std::shared_ptr<::Test::DPrx>>)] sequence<D*> DPrxList;

[cpp:type(std::list< ::Test::DPrxList>)] sequence<DPrxList> DPrxListList;
sequence<DPrxList> DPrxListSeq;
[cpp:type(std::list< ::Test::DPrxSeq>)] sequence<DPrxSeq> DPrxSeqList;

sequence<double> DoubleSeq;

[cpp:type(Test::CustomMap<Ice::Int, std::string>)] dictionary<int, string> IntStringDict;
dictionary<long, long> LongLongDict;
dictionary<string, int> StringIntDict;

class DictClass
{
    IntStringDict isdict;
}

[cpp:type(Test::CustomBuffer<bool>)] sequence<bool> BoolBuffer;
[cpp:type(Test::CustomBuffer<Ice::Short>)] sequence<short> ShortBuffer;
[cpp:type(Test::CustomBuffer<Ice::Int>)] sequence<int> IntBuffer;
[cpp:type(Test::CustomBuffer<Ice::Long>)] sequence<long> LongBuffer;
[cpp:type(Test::CustomBuffer<Ice::Float>)] sequence<float> FloatBuffer;
[cpp:type(Test::CustomBuffer<Ice::Double>)] sequence<double> DoubleBuffer;
[cpp:type(Test::CustomBuffer<Ice::Byte>)] sequence<byte> ByteBuffer;
struct BufferStruct
{
    ByteBuffer byteBuf;
    BoolBuffer boolBuf;
    ShortBuffer shortBuf;
    IntBuffer intBuf;
    LongBuffer longBuf;
    FloatBuffer floatBuf;
    DoubleBuffer doubleBuf;
}

[amd] interface TestIntf
{
    DoubleSeq opDoubleArray([cpp:array] DoubleSeq inSeq, out DoubleSeq outSeq);

    BoolSeq opBoolArray([cpp:array] BoolSeq inSeq, out BoolSeq outSeq);

    [cpp:array] ByteList opByteArray([cpp:array] ByteList inSeq, out [cpp:array] ByteList outSeq);

    VariableList opVariableArray([cpp:array] VariableList inSeq, out VariableList outSeq);

    [cpp:type(std::deque<bool>)] BoolSeq
    opBoolSeq([cpp:type(std::deque<bool>)] BoolSeq inSeq, out [cpp:type(std::deque<bool>)] BoolSeq outSeq);

    BoolList opBoolList(BoolList inSeq, out BoolList outSeq);

    [cpp:type(std::deque< ::Ice::Byte>)] ByteSeq
    opByteSeq([cpp:type(std::deque< ::Ice::Byte>)] ByteSeq inSeq,
              out [cpp:type(std::deque< ::Ice::Byte>)] ByteSeq outSeq);

    ByteList opByteList(ByteList inSeq, out ByteList outSeq);

    [cpp:type(MyByteSeq)] ByteSeq
    opMyByteSeq([cpp:type(MyByteSeq)] ByteSeq inSeq, out [cpp:type(MyByteSeq)] ByteSeq outSeq);

    [cpp:view-type(Util::string_view)] string
    opString([cpp:view-type(Util::string_view)] string inString,
             out [cpp:view-type(Util::string_view)] string outString);

    [cpp:type(std::deque<std::string>)] StringSeq
    opStringSeq([cpp:type(std::deque<std::string>)] StringSeq inSeq,
                out [cpp:type(std::deque<std::string>)] StringSeq outSeq);

    StringList opStringList(StringList inSeq, out StringList outSeq);

    [cpp:type(std::deque< ::Test::Fixed>)] FixedSeq
    opFixedSeq([cpp:type(std::deque< ::Test::Fixed>)] FixedSeq inSeq,
               out [cpp:type(std::deque< ::Test::Fixed>)] FixedSeq outSeq);

    FixedList opFixedList(FixedList inSeq, out FixedList outSeq);

    [cpp:type(std::deque< ::Test::Variable>)] VariableSeq
    opVariableSeq([cpp:type(std::deque< ::Test::Variable>)] VariableSeq inSeq,
                  out [cpp:type(std::deque< ::Test::Variable>)] VariableSeq outSeq);

    VariableList opVariableList(VariableList inSeq, out VariableList outSeq);

    [cpp:type(std::deque< ::Test::StringStringDict>)] StringStringDictSeq
    opStringStringDictSeq([cpp:type(std::deque< ::Test::StringStringDict>)] StringStringDictSeq inSeq,
                          out [cpp:type(std::deque< ::Test::StringStringDict>)] StringStringDictSeq outSeq);

    StringStringDictList opStringStringDictList(StringStringDictList inSeq, out StringStringDictList outSeq);

    [cpp:type(std::deque< ::Test::E>)] ESeq
    opESeq([cpp:type(std::deque< ::Test::E>)] ESeq inSeq, out [cpp:type(std::deque< ::Test::E>)] ESeq outSeq);

    EList opEList(EList inSeq, out EList outSeq);

    [cpp:type(std::deque<std::shared_ptr<::Test::DPrx>>)] DPrxSeq
    opDPrxSeq([cpp:type(std::deque<std::shared_ptr<::Test::DPrx>>)] DPrxSeq inSeq,
              out [cpp:type(std::deque<std::shared_ptr<::Test::DPrx>>)] DPrxSeq outSeq);

    DPrxList opDPrxList(DPrxList inSeq, out DPrxList outSeq);

    [cpp:type(std::deque<std::shared_ptr<Test::C>>)] CSeq
    opCSeq([cpp:type(std::deque<std::shared_ptr<Test::C>>)] CSeq inSeq,
           out [cpp:type(std::deque<std::shared_ptr<Test::C>>)] CSeq outSeq);

    CList opCList(CList inSeq, out CList outSeq);

    void opOutArrayByteSeq(ByteSeq org, out [cpp:array] ByteSeq copy);

    IntStringDict opIntStringDict(IntStringDict idict, out IntStringDict odict);

    [cpp:type(::Test::CustomMap< ::Ice::Long, ::Ice::Long>)] LongLongDict
    opVarDict([cpp:type(::Test::CustomMap<std::string, ::Ice::Int>)] StringIntDict idict,
              out [cpp:type(::Test::CustomMap<std::string, ::Ice::Int>)] StringIntDict odict);

    [cpp:view-type(::std::map< ::Ice::Int, ::Util::string_view>)] [cpp:type(::Test::CustomMap< ::Ice::Int, std::string>)] IntStringDict
    opCustomIntStringDict(
        [cpp:view-type(::std::map< ::Ice::Int, ::Util::string_view>)] [cpp:type(::Test::CustomMap< ::Ice::Int, std::string>)] IntStringDict idict,
        out [cpp:view-type(::std::map< ::Ice::Int, ::Util::string_view>)] [cpp:type(::Test::CustomMap< ::Ice::Int, std::string>)] IntStringDict odict);

    ShortBuffer opShortBuffer(ShortBuffer inS, out ShortBuffer outS);

    [cpp:type(::Test::CustomBuffer<bool>)] BoolSeq opBoolBuffer(
        [cpp:type(::Test::CustomBuffer<bool>)] BoolSeq inS,
        out [cpp:type(::Test::CustomBuffer<bool>)] BoolSeq outS);

    BufferStruct opBufferStruct(BufferStruct s);

    void shutdown();
}

}
